<?php

namespace Modules\Asset\Entities;

use Modules\Core\Entities\BaseEntity as Model;
use ThrowException;

use \Modules\Asset\Entities\WithdrawRecord;
use Setting;
use Cache;

// 常规类资产 (如积分、红包) 
class Asset extends Model
{
    protected $guarded = [];
    protected $table = 'assets';
    static public $resourceName = '';

    public function records()
    {
        return $this->hasMany('\Modules\Asset\Entities\AssetRecord', 'asset_id');
    }

    public function withdraw_records()
    {
        return $this->hasMany('\Modules\Asset\Entities\WithdrawRecord', 'asset_id');
    }

    // public function getBalanceAttribute($value)
    // {
    //     // return $this->mapActivityType($type);
    // }

    // public function setBalanceAttribute($value)
    // {
    //     // $this->activity_type = $this->mapActivityType($type);
    //     $this->attributes['activity_type'] = $this->mapActivityType($value);
    // }

    protected function change($type, $value, $options)
    {
        // 当前函数的缓存key
        $cachedFunKey = $this->uuid . '_change_fun';

        $lock = Cache::lock($cachedFunKey, 10);

        if (!$lock->get()) {
            // 无法锁定当前函数
            return false;
        }

        // 余额缓存的key
        $cachedBalanceKey = $this->uuid . '_balance';

        // 如果redis没有缓存当前余额或缓存的余额与当前值不一致刚需要重新读取
        $cachedBalance = Cache::get($cachedBalanceKey);
        if (!is_null($cachedBalance) && $cachedBalance !== $this->balance) {
            // 使用最新缓存数据
            $this->balance = $cachedBalance;
        }

        // 余额不足
        if ($type === 0 && $this->balance < $value) {
            $lock->release();
            return false;
        }

        $before = $this->balance;

        $this->balance += $value * ($type === 0 ? -1 : 1);;

        $this->save();

        // 缓存新的余额
        Cache::put($cachedBalanceKey, $this->balance, 3);

        $after = $this->balance;

        $this->records()->create([
            'uuid' => uniqid(),
            'order_id' => @$options['order']->id,
            'order_number' => @$options['order']->number,
            'user_id' => $this->target_id,
            'before' => $before,
            'after' => $after,
            'value' => $value,
            'type' => $type,
            'asset_type' => $this->type,
            'sub_type' => @$options['sub_type'] ?: 1,
            'description' => @v($options['description']),
            'admin_id' => @$options['admin']->id
        ]);

        $lock->release();
        return true;
    }

    public function in($value, $options = [])
    {
        return $this->change(1, $value, $options);
    }

    public function out($value, $options = [])
    {
        return $this->change(0, $value, $options);
    }

    public function frozen($value)
    {
        if ($this->balance < $value) {
            return false;
        }

        $this->frozen += $value;
        $this->balance -= $value;

        $this->save();

        return true;
    }

    public function unfrozen($value)
    {
        $this->frozen -= $value;
        $this->balance += $value;

        $this->save();
    }

    public function cleanFrozen($value)
    {
        $this->frozen -= $value;
        if ($this->frozen < 0) {
            $this->frozen = 0;
        }
        $this->save();
    }

    public function withdraw(Array $options)
    {
        $value = @$options['value'] ?: ThrowException::Conflict('请输入金额');
        $this->frozen($value) ?: ThrowException::Conflict('余额不足');

        $withdrawType = $options['withdraw_type'];

        $autoPayMaps = ['wechat_pay_auto', 'bank_auto'];
        $autoPayStatus = 0;

        if (in_array($withdrawType, $autoPayMaps))
        {
            // 自动转帐审核线
            $auditLine = @Setting::get('sys_redpack')['audit_line'] ?: 0;
            if ($value >= $auditLine) {
                $autoPayStatus = 2;
            }
            else {
                $autoPayStatus = 4;
            }
        }

        $item = WithdrawRecord::create([
            'uuid' => uniqid(),
            'asset_type' => $this->type,
            'asset_id' => $this->id,
            'user_id' => $this->target_id,
            'number' => WithdrawRecord::generateNumber(),
            'value' => $value,
            'withdraw_type' => $options['withdraw_type'],
            'account' => @$options['account'],
            'account_qrcode' => @$options['account_qrcode'],
            'phone' => @$options['phone'],
            'auto_pay_status' => $autoPayStatus,
            'bank_name' => @$options['bank_name'],
            'bank_account_name' => @$options['bank_account_name'],
            'bank_account_number' => @$options['bank_account_number'],
        ]);

        return $item;
    }
}
